import unittest

from pyremics.torqy.utility import split_to_strings_iter
import pyremics.torqy.treeseq as ptt
import pyremics.torqy.expression as pte
from c_macro_interpreter import *

def process(seq, exprs):
    for expr in exprs:
        #print "debug> seq=", "\n".join(.treeseq.seq_pretty(seq))
        if isinstance(expr, tuple):
            #print "debug> step: %s" % str(expr[0])
            expr = expr[1]
        if isinstance(expr, pte.TorqExpression):
            pos, foldCmds = expr.match(seq, 1)
            assert pos == len(seq)
            newSeq = ptt.seq_fold(seq, foldCmds)
            seq = newSeq
        else:
            seq = expr(seq)
    print "debug> seq=", "\n".join(ptt.seq_pretty(seq))
    #print "done."
    return seq

base_exprs = debug_build_exprs()

class TestCMacroInterpreter(unittest.TestCase):
    def test1st(self):
        print "debug> test1st"
        definitions = [ "-DA" ]
        macroInterpreter = MacroInterpreter()
        macroInterpreter.build_tables(definitions)
        
        exprs = list(base_exprs)
        for i, expr in enumerate(exprs):
            if expr is None: exprs[i] = macroInterpreter
        
        inputText = u"""
#define B
#if defined A || defined (B)
this_line_is_visible;
#elif defined A && A >= 0
this_line_should_be_removed;
#endif
"""
        seq = [ 'code' ]; seq.extend(split_to_strings_iter(inputText))
        seq = process(seq, exprs)
        prettied = ptt.seq_pretty(seq)
        self.assertEqual(len(prettied), 4)
        self.assertTrue("\n".join(prettied).find('not') < 0)

    def test2nd(self):
        print "debug> test2nd"
        definitions = [ "-DA" ]
        macroInterpreter = MacroInterpreter()
        macroInterpreter.build_tables(definitions)
        
        exprs = list(base_exprs)
        for i, expr in enumerate(exprs):
            if expr is None: exprs[i] = macroInterpreter
        
        inputText = u"""
#define B
#if ! defined A
this_line_should_not_be_visible;
#else
this_line_is_visible;
#endif
"""
        seq = [ 'code' ]; seq.extend(split_to_strings_iter(inputText))
        seq = process(seq, exprs)
        prettied = ptt.seq_pretty(seq)
        self.assertEqual(len(prettied), 4)
        self.assertTrue("\n".join(prettied).find('not') < 0)

    def test3rd(self):
        print "debug> test3rd"
        definitions = [ "-DA" ]
        macroInterpreter = MacroInterpreter()
        macroInterpreter.build_tables(definitions)
        
        exprs = list(base_exprs)
        for i, expr in enumerate(exprs):
            if expr is None: exprs[i] = macroInterpreter
        
        inputText = u"""
#if defined A
this_line_is_visible;
#if ! defined A
this_line_should_not_be_visible;
#else
this_line_is_visible_2;
#endif
#else
this_line_should_not_be_visible_2;
#endif
"""
        seq = [ 'code' ]; seq.extend(split_to_strings_iter(inputText))
        seq = process(seq, exprs)
        prettied = ptt.seq_pretty(seq)
        self.assertEqual(len(prettied), 6)
        self.assertTrue("\n".join(prettied).find('not') < 0)

    def test4th(self):
        print "debug> test4th"
        definitions = [ "-DA=B" ]
        macroInterpreter = MacroInterpreter()
        macroInterpreter.build_tables(definitions)
        
        exprs = list(base_exprs)
        for i, expr in enumerate(exprs):
            if expr is None: exprs[i] = macroInterpreter
        
        inputText = u"""
A;
the_above_line_should_be_B_not_A;
"""
        seq = [ 'code' ]; seq.extend(split_to_strings_iter(inputText))
        seq = process(seq, exprs)
        prettied = ptt.seq_pretty(seq)
        self.assertEqual(len(prettied), 6)

    def test5th(self):
        print "debug> test5th"
        definitions = [ "-NA" ]
        macroInterpreter = MacroInterpreter()
        macroInterpreter.build_tables(definitions)
        
        exprs = list(base_exprs)
        for i, expr in enumerate(exprs):
            if expr is None: exprs[i] = macroInterpreter
        
        inputText = u"""
#if defined A
this_line_should_not_be_visible;
#endif
#if A
this_line_should_not_be_visible_2;
#endif
"""
        seq = [ 'code' ]; seq.extend(split_to_strings_iter(inputText))
        seq = process(seq, exprs)
        prettied = ptt.seq_pretty(seq)
        self.assertTrue("\n".join(prettied).find('not') < 0)
    
    def test6th(self):
        print "debug> test5th"
        textSplitPattern = re.compile(r"\d+|[a-z_]+|.", re.DOTALL | re.IGNORECASE)
        inputText = u"""
int main(int argc, char *argv[]) {
    return 0;
}
"""
        seq = [ 'code' ]; seq.extend(split_to_strings_iter(inputText, textSplitPattern))
        print seq

unittest.main()

